﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Technosoftware.DaAeHdaClient.Da;
using Technosoftware.DaAeHdaClient;
using Technosoftware.DaAeHdaClient;
using Technosoftware.DaAeHdaClient.Da;
using FreeOPC.Config.Model;
using FreeOPC.Config;
using System.Threading;
using Technosoftware.DaAeHdaClient.Ae;
using OpcRcw.Da;
using System.Security.Cryptography;
using MQTTnet.Server;
using MQTTnet;
using FreeOPC.Server.MQTTService;
using Newtonsoft.Json;
using FreeOPC.Server.sqlite;
using System.Data;
using MQTTnet.Internal;
using Microsoft.AspNetCore.Hosting.Server;
using System.Text.RegularExpressions;

namespace FreeOPC.Server.OPCServer
{
    public partial class OpcDaServer : IDisposable
    {
        #region properties
        private TsCDaServer daServer;

        public OPCServerModel _serverConfig;

        public Task _daMonitor;
        public Task _daStarttask;
        private string _ip;

        private string _progID;

        private bool foundDisconnected = false;
        protected CancellationTokenSource _tokenSource;
        protected CancellationTokenSource _aoftokenSource;

        /// <summary>
        /// 等待时间
        /// </summary>
        private static int DA_CONNECTOR_MONITOR_INTERVAL = 1000 * 60 * 2;

        public int SubSystemTypeId
        {
            get;
            set;
        }

        private string[] decPtFmt = new string[]
        {
            "{0:#0.0}",
            "{0:#0.00}",
            "{0:#0.000}",
            "{0:#0.0000}",
            "{0:#0.00000}",
            "{0:#0.000000}",
            "{0:#0.0000000}",
            "{0:#0.00000000}",
            "{0:#0.000000000}",
            "{0:#0.0000000000}"
        };
        #endregion

        public OpcDaServer(OPCServerModel opcDaServer)
        {
            _serverConfig = opcDaServer;
            _tokenSource = new CancellationTokenSource();
            daServer = new TsCDaServer(new Technosoftware.DaAeHdaClient.Com.Factory(), new OpcUrl(opcDaServer.GetDAServerUrl()));

        }

        protected volatile bool _isShutDown = false;

        public static List<string> FirstItems { get; set; } = new();

        public void OnDAServerShutDown(string reason)
        {
            SerilogServer.WriteLog("OPCStartService", new string[] { "Receiving shutdown notification  " });
            Console.WriteLine("OnDAServerShutDown");
            _isShutDown = true;
        }

        void FireOpcConnectionMonitor()
        {
            _daMonitor= Task.Factory.StartNew(MonitorOPCSvr, _tokenSource.Token, _tokenSource.Token);
        }

        void MonitorOPCSvr(object token)
        {
            var isFirstTimeCheck = true;
            var cancellationToken = (CancellationToken)token;
            //var foundDisconnected = false;
            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    DisConnect();
                    break;
                }

                if (_isShutDown || foundDisconnected)
                {
                    Console.WriteLine("OnDAServerShutDown"+ _isShutDown.ToString()+ foundDisconnected.ToString());
                    #region Disconnect
                    try
                    {
                        //disconnect
                        DisConnect();
                    }
                    catch
                    {

                    }
                    #endregion

                    #region Reconnect OPC Server
                    try
                    {
                        SerilogServer.WriteLog("DAWindowsServiceLog", new string[] { "Connecting:", string.Format("Trying to connect to {0}...", _serverConfig.OPCServerIP) });
                        Connect();
                        SerilogServer.WriteLog("DAWindowsServiceLog", new string[] { "Connecting:", string.Format("Trying to connect to {0} finished.", _serverConfig.OPCServerIP) });
                        RegisterServerShutDown(OnDAServerShutDown);
                        InitItemFromDB(_serverConfig.OPCServerIP);
                        SerilogServer.WriteLog("DAWindowsServiceLog", new string[] { "Connecting:", string.Format("Trying to register shutdown event handler to {0} finished.", _serverConfig.OPCServerIP) });
                        _isShutDown = false;
                        foundDisconnected = false;
                        isFirstTimeCheck = true;
                    }
                    catch (Exception ex)
                    {
                        if (isFirstTimeCheck)
                        {
                            SerilogServer.WriteLog(
                               "DAWindowsServiceLog", new string[] {
                               string.Format("Trying connect to {0} failed {1}", _serverConfig.OPCServerIP, ex.Message)});
                            isFirstTimeCheck = true;
                        }
                        foundDisconnected = true;
                        try
                        {
                            if (IsDAServerConnected())
                            {
                                DisConnect();
                            }
                        }
                        catch
                        {

                        }
                    }
                    #endregion
                }
                else
                {
                    try
                    {
                        if (IsDAServerConnected())
                            foundDisconnected = false;
                        else
                            foundDisconnected = true;
                    }
                    catch (Exception exc)
                    {
                        if (isFirstTimeCheck)
                        {
                            SerilogServer.WriteErrorLog("DAWindowsServiceLog", string.Format("IsDAServerConnected raise exception on {0} errmsg:{1}", _serverConfig.Name, exc.Message), exc);
                            isFirstTimeCheck = true;
                        }
                        else
                        {
                            SerilogServer.WriteErrorLog("DAWindowsServiceLog", string.Format("When check the OPC Server connection, IsDAServerConnected raise exception on {0} errmsg:{1}", _serverConfig.Name, exc.Message), exc);

                        }
                        foundDisconnected = true;
                    }
                }

                try
                {
                    cancellationToken.WaitHandle.WaitOne(DA_CONNECTOR_MONITOR_INTERVAL);
                }
                catch
                {
                    break;
                }
            }
        }

        public void Stop()
        {
            try
            {
                SerilogServer.WriteLog("Stop", new string[] { "stop start:", string.Format("start  {0}...", _serverConfig.OPCServerIP) });
                
                foreach (var group in OPCGroups)
                {
                    group.DataChangedEvent -= OPCGroup_DataChangedEvent;
                }
                _tokenSource.Cancel();//在监控中会自动disconnect
                SerilogServer.WriteLog("Stop", new string[] { "stop complete:", string.Format("complete  {0}...", _serverConfig.OPCServerIP) });
            }
            catch (Exception ex)
            {
                SerilogServer.WriteLog("Stop", new string[] { "stop error:", string.Format("stop error  {0}...", _serverConfig.OPCServerIP+ex.Message+ex.StackTrace) });
            }
        }

        public void Start()
        {
             _daStarttask = new Task(() =>
            {
                try
                {
                    //connect to opc server and subscribe to opc server
                    SerilogServer.WriteLog("OPCStartService", new string[] { "Connecting:", string.Format("Connecting to {0}...", _serverConfig.OPCServerIP) });
                    Connect();
                    RegisterServerShutDown(OnDAServerShutDown);
                    if (OPCGroups != null)
                    {
                        OPCGroups.Clear();
                    }
                    InitItemFromDB(_serverConfig.OPCServerIP);
                    SerilogServer.WriteLog("OPCStartService", new string[] { "Registering:", string.Format("Registering shutdown event handler to {0} finished.", _serverConfig.OPCServerIP) });
                    _isShutDown = false;
                }
                catch (Exception ex)
                {
                    foundDisconnected = true;
                    SerilogServer.WriteLog("OPCStartService", new string[] { "Connecting:", string.Format("Connecting to {0} failed {1}", _serverConfig.OPCServerIP, ex.Message) });
                    Console.WriteLine(ex.Message+ex.StackTrace);
                    try
                    {
                        DisConnect();
                    }
                    catch
                    {

                    }
                }
                finally
                {
                    SerilogServer.WriteLog("OPCStartService", new string[] { "Starting OPC connection monitor." });
                    FireOpcConnectionMonitor();
                    SerilogServer.WriteLog("OPCStartService", new string[] { "Starting OPC connection monitor finished." });
                }
            }, TaskCreationOptions.LongRunning);
            _daStarttask.Start();
        }

        public void InitItemFromDB(string opcipc)
        {
            //var itemList = SqliteHelper.GetDataTable("select * from opctagitem where OPCIP='"+opcipc+"'");
            var groups = SqliteHelper.GetDataTable("select distinct(GroupName) from opctagitem where OPCIP='" + opcipc + "'");
            foreach (DataRow item in groups.Rows)
            {
                var groupName = item[0].ToString();
                RemoveServerSubScript(groupName);
                RegisterServerSubScript(item[0].ToString());
                var itemList = SqliteHelper.GetDataTable("select * from opctagitem where OPCIP='" + opcipc + "' and GroupName='"+ groupName + "'");
                List<string> items = new List<string>();
                foreach (DataRow tagitemRow in itemList.Rows)
                {
                    var TagItem = tagitemRow["TagItem"].ToString();
                    items.Add(TagItem);
                }
                AddItemList(items, groupName);
            }

            //foreach (DataRow item in itemList.Rows)
            //{
            //    var TagItem = item["TagItem"].ToString();
            //    var groupname = item["GroupName"].ToString();
            //    AddItem(TagItem, groupname);
            //}
            //AddItemList()
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        /// <param name="opcDaServer"></param>
        /// <returns></returns>
        public static string TempConnect(OPCServerModel opcDaServer)
        {
            try
            {
                var tempdaServer = new TsCDaServer(new Technosoftware.DaAeHdaClient.Com.Factory(), new OpcUrl(opcDaServer.GetDAServerUrl()));
                tempdaServer.Connect();
                Thread.Sleep(100);
                tempdaServer.Disconnect();
                return "True";
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }

        /// <summary>
        /// 连接OPC
        /// </summary>
        public void Connect()
        {
            try
            {
                daServer.Connect();
                Console.WriteLine("connect success!");
            }
            catch (Exception ex)
            {
                Dispose();
                throw ex;
            }
        }

        public bool IsDAServerConnected()
        {
            if (daServer != null)
            {
                if (daServer.GetServerStatus().ServerState == OpcServerState.Operational && IsOPCConnect())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public bool IsOPCConnect()
        {
            if (daServer != null)
            {
                var cc = daServer.GetProperties(new OpcItem[] { new OpcItem("!") }, new TsDaPropertyID[] { new TsDaPropertyID(5101) }, false);
                return true;
            }
            else
                return false;
        }

        public List<TsCDaSubscription> OPCGroups;


        public void RegisterServerShutDown(Action<string> callBack)
        {
            if (callBack != null)
            {
                daServer.ServerShutdownEvent += new OpcServerShutdownEventHandler(callBack);
            }
        }

        /// <summary>
        /// 注册订阅
        /// </summary>
        /// <param name="callBack"></param>
        public void RegisterServerSubScript(string groupName)
        {
            SerilogServer.WriteLog("RegisterServerSubScript", new string[] { "RegisterServerSubScript start." + groupName });
            if (OPCGroups == null)
            {
                OPCGroups = new List<TsCDaSubscription>();
            }

            

            if (!OPCGroups.Any(o => o.Name == groupName))
            {
                SerilogServer.WriteLog("RegisterServerSubScript", new string[] { "OPCGroups.Any." + groupName });
                TsCDaSubscriptionState st = new TsCDaSubscriptionState();
                st.Active = true;
                st.Name = groupName;
                st.ClientHandle = groupName;
                
                var OPCGroup = (TsCDaSubscription)daServer.CreateSubscription(st);
                OPCGroup.DataChangedEvent += OPCGroup_DataChangedEvent;
                SerilogServer.WriteLog("RegisterServerSubScript", new string[] { "OPCGroups add event change" + groupName });
                OPCGroups.Add(OPCGroup);
                SerilogServer.WriteLog("RegisterServerSubScript", new string[] { "OPCGroups end" + groupName });
            }

        }

        public void RemoveServerSubScript(string groupName)
        {
            if (OPCGroups == null)
            {
                OPCGroups = new List<TsCDaSubscription>();
            }
            var opcGroupModel = OPCGroups.Where(o => o.Name == groupName).FirstOrDefault();
            if (opcGroupModel!=null)
            {
                try
                {
                    SerilogServer.WriteLog("RemoveServerSubScript", new string[] { "RemoveServerSubScriptstart." + groupName });
                    OPCGroups.Remove(opcGroupModel);
                    daServer.CancelSubscription(opcGroupModel);
                    SerilogServer.WriteLog("RemoveServerSubScript", new string[] { "RemoveServerSubScriptfinished." });
                }
                catch (Exception ex) {
                    SerilogServer.WriteLog("RemoveServerSubScript", new string[] { "RemoveServerSubScript error."+groupName+ex.Message+ex.StackTrace });
                }
            }
        }

        public bool AddItem(string item,string groupName)
        {
            //强制先移除，再订阅
            RemoveItem(item, groupName);

            SerilogServer.WriteLog("AddItem1", new string[] { "AddItem start"+ item });
            TsCDaItem[] items = new TsCDaItem[1];
            items[0] = new TsCDaItem();
            items[0].ItemName = item;
            items[0].ClientHandle = item;
            if (OPCGroups == null)
            {
                SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroups is null RegisterServerSubScript" + item });
                RegisterServerSubScript(groupName);
            }
            var OPCGroup= OPCGroups.Where(o => o.Name == groupName).FirstOrDefault();
            if (OPCGroup != null)
            {
                SerilogServer.WriteLog("AddItem1", new string[] { "FirstItems judge start" +  item });
                if (!FirstItems.Any(o => o == item))
                {
                    FirstItems.Add(item);
                }
                SerilogServer.WriteLog("AddItem1", new string[] { "FirstItems judge end"+ item });
                try
                {
                    SerilogServer.WriteLog("AddItem1", new string[] { "AddItem start." + item });
                    if ((OPCGroup.Items != null && !OPCGroup.Items.Any(o => o.ItemName == item))|| OPCGroup.Items == null)
                    {
                        SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup judge " + item });
                        var result = OPCGroup.AddItems(items);
                        SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.AddItems " + item });

                        if (result[0].Result.IsOk())
                        {
                            SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.IsOk " + item });
                            return true;
                        }
                        else
                        {
                            SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.NOk " + item });
                            return false; 
                        }
                    }
                    else
                    {
                        SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.IsOk " + item });
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    SerilogServer.WriteLog("AddItem1", new string[] { "AddItem error. FirstItems.Remove start" + ex.Message + ex.StackTrace });
                    FirstItems.Remove(item);
                    SerilogServer.WriteLog("AddItem1", new string[] { "AddItem error." + ex.Message+ex.StackTrace });
                    return false;
                }
            }
            else
            {
                SerilogServer.WriteLog("AddItem1", new string[] { "RegisterServerSubScript start groupName is " + groupName });
                RegisterServerSubScript(groupName);
                SerilogServer.WriteLog("AddItem1", new string[] { "RegisterServerSubScript end groupName is " + groupName });
                OPCGroup = OPCGroups.Where(o => o.Name == groupName).FirstOrDefault();
                FirstItems.Add(item);
                try
                {
                    SerilogServer.WriteLog("AddItem1", new string[] { "AddItem error." + item });
                    if ((OPCGroup.Items != null && !OPCGroup.Items.Any(o => o.ItemName == item))|| OPCGroup.Items == null)
                    {
                        SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup judge " + item });
                        var result = OPCGroup.AddItems(items);
                        if (result[0].Result.IsOk())
                        {
                            SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.IsOk " + item });
                            return true;
                        }
                        else
                        {
                            SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.NOk  " + item });
                            return false; }
                    }
                    else
                    {
                        SerilogServer.WriteLog("AddItem1", new string[] { "OPCGroup.IsOk " + item });
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    FirstItems.Remove(item);
                    SerilogServer.WriteLog("AddItem1", new string[] { "AddItem error." + ex.Message });
                    return false;
                }

            }
        }

        public void AddItemList(List<string> titems, string groupName)
        {
            TsCDaItem[] items = new TsCDaItem[titems.Count];
            for (int i = 0; i < titems.Count; i++)
            {
                items[i] = new TsCDaItem();
                items[i].ItemName = titems[i];
                items[i].ClientHandle = titems[i];  
            }
            var OPCGroup = OPCGroups.Where(o => o.Name == groupName).FirstOrDefault();
            if (OPCGroup != null)
            {
                try
                {
                    if (FirstItems == null)
                    {
                        FirstItems = new List<string>();
                    }
                    FirstItems.AddRange(titems);

                    foreach (string item in titems)
                    {
                        SerilogServer.WriteLog("AddItemList", new string[] { "AddItemList " + item });
                    }

                    OPCGroup.AddItems(items);
                }
                catch (Exception ex)
                {
                    titems.ForEach(o => FirstItems.Remove(o));
                    SerilogServer.WriteLog("AddItemList", new string[] { "AddItemList error." + ex.Message+ex.StackTrace });
                }
            }
        }

        public void RemoveItem(string item, string groupName)
        {
            TsCDaItem[] items = new TsCDaItem[1];
            items[0] = new TsCDaItem();
            //items[0].ItemName = item;
            //items[0].ClientHandle = item;
            //items[0].Active = false;
            if (OPCGroups != null)
            {
                Console.WriteLine(groupName + " RemoveItem1");
                var OPCGroup = OPCGroups.Where(o => o.Name == groupName).FirstOrDefault();
                if (OPCGroup != null)
                {
                    if (OPCGroup.Items != null)
                    {
                        var itemModel = OPCGroup.Items.Where(o => o.ItemName == item).FirstOrDefault();
                        if (itemModel != null)
                        {
                            items[0] = itemModel;
                            items[0].Active = false;
                            Console.WriteLine(items[0].ItemName + " RemoveItem2" + OPCGroup.ServerHandle);
                            var result = OPCGroup.RemoveItems(items); ;
                            Console.WriteLine(result[0].Result.Code.ToString() + "|" + result[0].Result.Succeeded().ToString() + "|" + result[0].Result.Description().ToString());
                        }
                    }
                }
            }
        }


        private string topicName="mqttBusTopic";

        /// <summary>
        /// 订阅接收
        /// </summary>
        /// <param name="subscriptionHandle"></param>
        /// <param name="requestHandle"></param>
        /// <param name="values"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void OPCGroup_DataChangedEvent(object subscriptionHandle, object requestHandle, TsCDaItemValueResult[] values)
        {
            //SerilogServer.WriteLog("OPCGroup_DataChangedEvent", new string[] { "OPCGroup_DataChangedEvent start"  });
            ChangedItem e = new ChangedItem();
            e.Items = new string[values.Length];
            e.Values = new object[values.Length];
            for (int i = 0; i < values.Length; i++)
            {

                //if (!FirstItems.Any(o => o == values[i].ItemName))
                //{
                    e.Items[i] = values[i].ItemName;
                    e.Values[i] = values[i].Value;
                //}
                //else
                //{
                //    //如果存在第一次则不进行推送，并清除第一次的list的数据
                //    e.Items[i] =null;
                //    e.Values[i] = null;
                //    FirstItems.Remove(values[i].ItemName);
                //}
            }
            //var newItems = e.Items.Where(o => o != null).ToArray();
            //var newValues = e.Values.Where(o => o != null).ToArray();
            //e.Items = newItems;
            //e.Values = newValues;
            e.CreateTime= DateTime.Now;
            e.OPCIP = _serverConfig.OPCServerIP;
            e.GroupeName = subscriptionHandle.ToString();

           
            if (e.Items.Count() > 0)
            {
                //SerilogServer.WriteLog("OPCGroup_DataChangedEvent", new string[] { "send mqtt start" });
                var msg = JsonConvert.SerializeObject(e);
                //SerilogServer.WriteLog("OPCGroup_DataChangedEvent", new string[] { "send mqtt start" + msg });
                var message = new MqttApplicationMessageBuilder().WithTopic(topicName).WithPayload(msg).Build();
                // Now inject the new message at the broker.
                MqttService.mqttServer.InjectApplicationMessage(
                   new InjectedMqttApplicationMessage(message)
                   {
                       SenderClientId = "123456"
                   });
                //SerilogServer.WriteLog("OPCGroup_DataChangedEvent", new string[] { "send mqtt end" + e.Items });
            }
        }

        /// <summary>
        /// 断开OPC
        /// </summary>
        public void DisConnect()
        {
            try
            {
                daServer.Disconnect();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Dispose()
        {
            if (daServer != null)
            {
                try
                {
                    daServer.Disconnect();
                }
                catch
                {

                }
                finally
                {
                    //daServer = null;
                }
            }
        }

        /// <summary>
        /// 根据tagname 获取属性编号 批量的 
        /// </summary>
        /// <param name="itemNames">tag的 名称</param>
        /// <param name="propertiyIDs">属性的ID， 根据DA的工具可以查看</param>
        /// <returns></returns>
        public TsCDaItemPropertyCollection[] GetItemProperties(String[] itemNames, int[] propertiyIDs)
        {
            var itemIdentifiers = new List<OpcItem>();
            foreach (var itemName in itemNames)
            {
                itemIdentifiers.Add(new OpcItem(itemName));
            }

            var propertyIDs = new List<TsDaPropertyID>();
            foreach (var pid in propertiyIDs)
            {
                propertyIDs.Add(new TsDaPropertyID(pid));
            }

            var properties = daServer.GetProperties(
                itemIdentifiers.ToArray(),
                propertyIDs.ToArray(),
                true);

            return properties;
        }

        private static readonly object lockobj = new object();

        /// <summary>
        /// 读出tag item 的value值
        /// </summary>
        /// <param name="itemNames">如：FPC001.SH</param>
        /// <returns></returns>
        public TsCDaItemValueResult[] ReadTagItemValue(List<string> itemNames)
        {
            lock (lockobj)
            {
                var items = new TsCDaItem[itemNames.Count];
                for (int i = 0; i < items.Length; i++)
                {
                    items[i] = new TsCDaItem(new OpcItem(itemNames[i]));
                }
                TsCDaItemValueResult[] values = null;
                try
                {
                    values = daServer.Read(items);
                }
                catch (Exception exc)
                {
                    values = new TsCDaItemValueResult[itemNames.Count];
                    foreach (var value in values)
                    {
                        if (value != null)
                        {
                            var r = value as TsCDaItemValueResult;
                            r.Result = OpcResult.S_FALSE;
                            r.Value = "?";
                            r.ClientHandle = exc.Message;
                        }
                    }
                }
                return values;
            }
        }

        /// <summary>
        /// 写值
        /// </summary>
        /// <param name="itemNames"></param>
        /// <returns></returns>
        public OpcItemResult[] WriteTagItemValue(Dictionary<string, string> itemNames)
        {
            var items = new TsCDaItemValue[itemNames.Count];
            for (int i = 0; i < items.Length; i++)
            {
                (string key, string value) = itemNames.ElementAt(i);
                items[i] = new TsCDaItemValue()
                {
                    Value = value,
                    ItemName = key,
                    ClientHandle = value
                };
            }
            OpcItemResult[] values = null;
            try
            {
                values = daServer.Write(items);
            }
            catch (Exception exc)
            {
                values = new OpcItemResult[itemNames.Count];
                foreach (var value in values)
                {
                    var r = value as OpcItemResult;
                    r.Result = OpcResult.S_FALSE;
                    r.ClientHandle = exc.Message;
                }
            }
            return values;
        }

        /// <summary>
        /// 获取所有的FCS 的station
        /// </summary>
        /// <returns></returns>
        public List<FCSStation> GetAllFCSStationNames()
        {
            var stations = new List<FCSStation>();
            TsCDaBrowsePosition position = null;

            var filter = new TsCDaBrowseFilters();
            filter.ReturnAllProperties = false;
            filter.ReturnPropertyValues = false;
            filter.ElementNameFilter = "FCS*";

            //var results = daServer.Browse(null, filter, out position);
            //.
            var browser = daServer.Browse(null, filter, out position);
            ////browser.Filter = "FCS*";
            var stationsCount = browser.Length;

            for (int i = 0; i < stationsCount; i++)
            {
                var station = browser[i].Name;
                stations.Add(new FCSStation() { StationName = station });
            }
            return stations;
        }

        /// <summary>
        /// 获取所有的station 名称
        /// </summary>
        /// <returns></returns>
        public List<FCSStation> GetAllStations()
        {
            TsCDaBrowsePosition position = null;

            var filter = new TsCDaBrowseFilters();
            filter.ReturnAllProperties = false;
            filter.ReturnPropertyValues = false;

            var browser = daServer.Browse(null, filter, out position);
            //browser.Filter = "FCS*";
            var stationsCount = browser.Length;
            var stations = new List<FCSStation>();
            for (int i = 0; i < stationsCount; i++)
            {
                var station = browser[i].Name;
                stations.Add(new FCSStation() { StationName = station });
            }
            return stations;
        }

        private string GetDomainName(string stationName)
        {
            foreach (var c in stationName)
            {
                if (Char.IsDigit(c))
                {
                    var index = stationName.IndexOf(c);
                    var domainNumber = stationName.Substring(index, 2);
                    return domainNumber;
                    //"DOMAIN" +
                }
            }
            return null;
        }


        /// <summary>
        /// 根据stationName 获取所有的tag 名称
        /// </summary>
        /// <param name="stationName"></param>
        /// <returns></returns>
        public List<ItemName> GetTagsByStation(string stationName)
        {

            List<ItemName> tags = new List<ItemName>();
            TsCDaBrowsePosition position = null;

            var filter = new TsCDaBrowseFilters();
            filter.ReturnAllProperties = false;
            filter.ReturnPropertyValues = false;

            var browser = daServer.Browse(new OpcItem(stationName), filter, out position);
            //browser.Filter = "FCS*";
            //var tags = browser.Length;

            for (int i = 0; i < browser.Length; i++)
            {
                var tag = browser[i].Name;
                tags.Add(new ItemName { Name = tag, StationName = stationName });
            }
            return tags;
        }
    }
}
